package com.springboot.tools.handler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.springboot.tools.annotations.IdType;
import com.springboot.tools.toolkit.IdWorker;
import com.springboot.tools.toolkit.TableInfo;
import com.springboot.tools.toolkit.TableInfoHelper;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;

public class MybatisDefaultParameterHandler extends DefaultParameterHandler {

    public MybatisDefaultParameterHandler(MappedStatement mappedStatement,
                                          Object parameterObject, BoundSql boundSql) {
        super(mappedStatement, processBatch(mappedStatement, parameterObject),
                boundSql);
    }


    protected static Object processBatch(MappedStatement ms,
                                         Object parameterObject) {
        Collection<Object> parameters = getParameters(parameterObject);
        if (parameters != null) {
            List<Object> objList = new ArrayList<Object>();
            for (Object parameter : parameters) {
                objList.add(populateKeys(ms, parameter));
            }
            return objList;
        } else {
            return populateKeys(ms, parameterObject);
        }
    }

    @SuppressWarnings(
            {"rawtypes", "unchecked"})
    protected static Collection<Object> getParameters(Object parameter) {
        Collection<Object> parameters = null;
        if (parameter instanceof Collection) {
            parameters = (Collection) parameter;
        } else if (parameter instanceof Map) {
            Map parameterMap = (Map) parameter;
            if (parameterMap.containsKey("collection")) {
                parameters = (Collection) parameterMap.get("collection");
            } else if (parameterMap.containsKey("list")) {
                parameters = (List) parameterMap.get("list");
            } else if (parameterMap.containsKey("array")) {
                parameters = Arrays
                        .asList((Object[]) parameterMap.get("array"));
            }
        }
        return parameters;
    }

    protected static Object populateKeys(MappedStatement ms,
                                         Object parameterObject) {
        if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(parameterObject
                    .getClass());
            if (tableInfo != null && tableInfo.getIdType() == IdType.ID_WORKER) {
                MetaObject metaParam = ms.getConfiguration().newMetaObject(
                        parameterObject);
                Object idValue = metaParam.getValue(tableInfo.getKeyProperty());
                if (idValue == null) {

                    metaParam.setValue(tableInfo.getKeyProperty(),
                            IdWorker.getId());
                }
                return metaParam.getOriginalObject();
            }
        }
        return parameterObject;
    }

}
